Skip to main content

什么是Vue

Vue是构建用户界面的 JavasScriptMVVM 框架。

那么到底什么是 MVVM

Alternate text

  • M(Model):数据层;例如 Vue2 实例中的 data
  • V(View):视图(DOM)
  • VM(ViewModel):Vue胶水层代码;它负责 监听数据的变化 和 视图的更新,同时也是 Model 数据 和 View 视图通信的一个桥梁
ACE 的理解

MVVM 又叫数据驱动视图,所以视图的改变源于数据的更新。

Alternate text

ACE 的理解

Vue 在实例化的过程中会对遍历传给 实例化对象选项中的 data选项 遍历其所有属性 并使用 Object.defineProperty 把这些属性全部转为 getter/setter

ACE 的理解

Vue 最重要的两个 function 监听 Observer 和 编译 Compile

Observer

  • Observer 基本干了什么事情
    • 劫持并监听所有属性
      • 在 Observer 函数中
    • 采用的方式
      • Vue2 Object.defineProperty
      • Vue3 new Proxy
vue2.6.7 Observer 的方法
export class Observer {
value: any;
dep: Dep;
vmCount: number;

constructor (value: any) {
this.value = value
// 一个 Dep 对象的实例,Watcher 和 Observer 之间的桥梁
this.dep = new Dep()
this.vmCount = 0
// 把自身 this 添加到 value 的 __ob__ 属性上
def(value, '__ob__', this)
// 对 value 的类型进行判断
if (Array.isArray(value)) {
if (hasProto) {
protoAugment(value, arrayMethods)
} else {
copyAugment(value, arrayMethods, arrayKeys)
}
this.observeArray(value)
} else {
this.walk(value)
}
}
}

常见问题

  • data 为什么需要是个函数

    • 因为 js 的对象是按引用传递的,如果使用对象的话,会导致组件内数据无法保持唯一,可能会被其他组件数据修改,所以需要使用函数,每次都重新创建一个新的对象实现。
  • 响应式原理

    • 通过 defineProperydata 内的属性遍历添加 gettersetter 属性,通过 watcherDep 进行依赖收集管理,内部会通过 Dep.target 去维护一个当前的 watcher ,当数据更新的时候会去执行 dep.notify 方法,依次遍历当前 dep 内的 watcher 进行数据更新。

    • Observer 用于添加 gettersetter

    • Dep 进行依赖收集 (收集的依赖就是 watcher)。

    • Watcher 主要负责保存依赖,从而在数据更新的时候,触发渲染。

Watcher 的类别
  • data watcher
  • watch watcher
  • computed watcher
    • 在实例上保存了个 lazydirty 属性。
    • 如果当前的 dirtytrue ,说明就需要重新计算,则调用 watcher.evaluate 方法进行计算。
    • watcher 创建的时候,默认是不会调用 get 方法进行依赖收集。
    • 只有在数据发生变化的时候,会去调用 watcher.update, 然后再这里面调用 watcher.run ,进而去调用 get 方法收集依赖,或者数据发生变化的时候,也会重新收集依赖。

computed

  • 调用 initComputed 进行初始化,对 computed 内的每个对象创建一个 watcher
  • 如果 computed 是个函数,就调用 createComputedGetter 否则调用 createGetterInvoker,并通过 defineProperty 挂载到实例上,重写 get 方法。

watch

  • 调用 initWatch 进行初始化,并对 watch 内的每个属性,创建一个 watcher
  • 如果 val 是对象,贼调用 val.handler,是 string,则从 this 中获取,否则 val 就是个函数
  • watch 的每个属性调用 vm.$watch 进行处理
  • 依然创建一个watcher,如果当前 watch 有 immediate 属性,则立刻执行

性能指标

FP(First Paint)首次绘制 FCP (First Contentful Paint) 首次内容绘制 LCP(Largest Contentful Paint)最大内容绘制 DCL (DocumentContentLoaded) dom加载完成 L (Onload)页面加载完成 TTI(Time To Interactive)可交互 TBT (Total Blocking Time)页面阻塞总时长 FID (First Input Delay)首次输入延迟 CLS (Cumlative Layout Shift)累计布局偏移 SI (Speed Index) 首次显示页面可见部分的平均时间

雅虎35条军规前端性能优化之雅虎35条军规

  • 服务器

    • 使用cdn
    • 使用浏览器缓存
    • 启用gzip
    • 配置etag
    • ajax使用get请求(get可以被缓存,post不会)
    • 避免图片src为空
    • 尽早输出内容(服务端渲染)
  • 页面内容

    • 减少http请求
    • 减少dns查询
    • 避免重定向
    • 缓存ajax请求
    • 延迟加载
    • 预加载
    • 减少dom元素数量
    • 划分内容到不同域名
    • 减少iframe使用
    • 减少404
    • 保持单个文件小于25kb
    • 打包内容为分段multipart文档
  • Cookie

    • 减少cookie大小
    • 静态资源使用无cookie的域名
  • 图片

    • 尽可能使用webp
    • css sprite(雪碧图)
    • 使用体积小,可缓存的favicon.ico
  • js

    • script放页面底部
    • 使用外部 js 和 css
    • 压缩 css js
    • 删除重复脚本
    • 减少dom操作
    • 使用高效的事件处理
  • css

    • 把样式表放在head内
    • 不用使用css表达式
    • 使用link代替@import
    • 不要使用filter(不是css3的filter,ie的东西)

重排重绘的操作读写分离 getComputedStyle currentStyle

重排: 页面初始渲染,这是开销最大的一次重排 添加/删除可见的DOM元素 改变元素位置 改变元素尺寸,比如边距、填充、边框、宽度和高度等 改变元素内容,比如文字数量,图片大小等 改变元素字体大小 改变浏览器窗口尺寸,比如resize事件发生时

重绘: 当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘

1.HTML 被 HTML 解析器解析成 DOM 树; 2.CSS 被 CSS 解析器解析成 CSSOM 树; 3.结合 DOM 树和 CSSOM 树,生成一棵渲染树(Render Tree),这一过程称为 Attachment; 4.生成布局(flow),浏览器在屏幕上“画”出渲染树中的所有节点; 5.将布局绘制(paint)在屏幕上,显示出整个页面。 第四步和第五步是最耗时的部分,这两步合起来,就是我们通常所说的渲染。